﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Antlers
{
	internal class OperationQueue<T>
	{
		private Queue<Operation> m_operations;
		private object m_operationsLock = new object();
		private Operation m_currentOperation;

		public delegate void OperationDelegate(T context);

		internal OperationQueue(T context, OperationDelegate operation)
		{
			m_operations = new Queue<OperationQueue<T>.Operation>(new Operation[] { new Operation(context, operation) });
		}

		internal OperationQueue(IEnumerable<T> contextList, OperationDelegate operation)
		{
			m_operations = new Queue<Operation>(contextList.Count());
			foreach (T context in contextList)
			{
				m_operations.Enqueue(new Operation(context, operation));
			}
		}

		public void Start()
		{
			EnsureExecution();
		}

		private void EnsureExecution()
		{
			Lock.RunSafe(
				m_operationsLock,
				() =>
				{
					return m_operations.Count > 0 && m_currentOperation == null;
				},
				() =>
				{
					m_currentOperation = m_operations.Dequeue();

					ThreadPool.QueueUserWorkItem((object state) =>
					{
						m_currentOperation.Execute();
						m_currentOperation = null;
						EnsureExecution();
					});
				});
		}

		private class Operation
		{
			private T m_context;
			private OperationDelegate m_operation;

			public Operation(T context, OperationDelegate operation)
			{
				m_context = context;
				m_operation = operation;
			}

			public void Execute()
			{
				m_operation(m_context);
			}
		}
	}
}
